package com.iceframework.core.thread.utils;

import java.util.ArrayList;
import java.util.Date;
import java.util.Hashtable;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.Executors;
import java.util.concurrent.ThreadPoolExecutor;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.iceframework.core.thread.entity.ThreadPoolDispatcherEntity;

public class ThreadPoolDispatcherUtils {

	private static final int DEFAULT_MAX_THREAD_NUM = 10;

	/**
	 * 全局线程容器
	 */
	private static Map<String, ThreadPoolDispatcherEntity> threadContainer = null;
	static protected Logger logger = LoggerFactory.getLogger(ThreadPoolDispatcherUtils.class);
	private static ThreadPoolExecutor systemThreadPool = null;

	static {
		if (threadContainer == null) {
			threadContainer = new Hashtable<>();
			systemThreadPool = createSystemThreadPool();
			// 检查容器内是否有已停止线程
			systemThreadPool.execute(new Runnable() {
				@Override
				public void run() {
					try {
						startCheck();
					} catch (InterruptedException e) {
						e.printStackTrace();
					}
				}
			});
		}
	}

	/**
	 * 查询线程容器
	 * 
	 * @return
	 */
	public static List<ThreadPoolDispatcherEntity> listThreadPoolContainer() {
		List<ThreadPoolDispatcherEntity> entitys = new ArrayList<ThreadPoolDispatcherEntity>();
		Set<String> keySet = threadContainer.keySet();
		List<String> arrayList = new ArrayList<>(keySet);
		for (String string : arrayList) {
			ThreadPoolDispatcherEntity threadEntity = new ThreadPoolDispatcherEntity();
			ThreadPoolDispatcherEntity threadDispatcherEntity = threadContainer.get(string);
			ThreadPoolExecutor threadPoolExecutor = threadDispatcherEntity.getThreadPoolExecutor();
			threadEntity.setKey(threadDispatcherEntity.getKey());
			threadEntity.setStartDate(threadDispatcherEntity.getStartDate());
			threadEntity.setStatus("Alive");
			threadEntity.setPoolSize(threadPoolExecutor.getPoolSize());
			threadEntity.setMaximumPoolSize(threadPoolExecutor.getMaximumPoolSize());
			threadEntity.setTaskCount(threadPoolExecutor.getTaskCount());
			threadEntity.setCompletedTaskCount(threadPoolExecutor.getCompletedTaskCount());
			entitys.add(threadEntity);
		}
		return entitys;
	}

	/**
	 * 开启线程池检查（包含移除操作，必须启动）
	 * @throws InterruptedException
	 */
	public static void startCheck() throws InterruptedException {
		while (true) {
			Set<String> keysSet = threadContainer.keySet();
			List<String> arrayList = new ArrayList<>(keysSet);
			for (String key : arrayList) {
				ThreadPoolExecutor threadPoolExecutor = threadContainer.get(key).getThreadPoolExecutor();
				if (threadPoolExecutor.isTerminated()) {
					threadContainer.remove(key);
				}
			}
			Thread.sleep(500);
		}
	}

	/**
	 * 创建系统线程池
	 * @return
	 */
	private static ThreadPoolExecutor createSystemThreadPool() {
		logger.debug("初始化系统线程池");
		ThreadPoolExecutor thread = (ThreadPoolExecutor) Executors.newFixedThreadPool(getDefaultThreadNumber()); // 固定个数线程
		String threadKey = getThreadKey(ThreadPoolDispatcherUtils.class, "System");
		threadContainer.put(threadKey, getThreadDispatcherEntity(threadKey, thread));
		return thread;
	}

	/**
	 * 执行任务
	 * @param clz
	 * @param tag
	 * @param runnable
	 */
	public static void executeTask(Class<?> clz, String tag, Runnable runnable) {
		logger.info(getThreadKey(clz, tag) + "执行任务");
		systemThreadPool.execute(runnable);
	}

	/**
	 * 申請線程池
	 * @param clz
	 * @param tag
	 * @return
	 */
	public synchronized static ThreadPoolExecutor mallocThreadPool(Class<?> clz, String tag) {
		logger.info(getThreadKey(clz, tag) + "申请获取线程池");
		String threadKey = getThreadKey(clz, tag);
		if (threadContainer.containsKey(threadKey)) {
			return threadContainer.get(threadKey).getThreadPoolExecutor();
		}
		ThreadPoolExecutor thread = (ThreadPoolExecutor) Executors.newFixedThreadPool(getDefaultThreadNumber()); // 固定个数线程
		threadContainer.put(threadKey, getThreadDispatcherEntity(threadKey, thread));
		return thread;
	}

	/**
	 * 申请线程池
	 * @param clz
	 * @param tag
	 * @param number
	 * @return
	 */
	public synchronized static ThreadPoolExecutor mallocThreadPool(Class<?> clz, String tag, int number) {
		logger.info(getThreadKey(clz, tag) + "申请获取线程池");
		String threadKey = getThreadKey(clz, tag);
		if (threadContainer.containsKey(threadKey)) {
			return threadContainer.get(threadKey).getThreadPoolExecutor();
		}
		ThreadPoolExecutor thread = (ThreadPoolExecutor) Executors.newFixedThreadPool(number); // 固定个数线程
		threadContainer.put(threadKey, getThreadDispatcherEntity(threadKey, thread));
		return thread;
	}

	/**
	 * 强制停止线程
	 * 
	 * @param key    线程分发key
	 * @param number
	 * @return boolean
	 */
	public synchronized static boolean shutdownThreadPool(String key) {
		ThreadPoolExecutor threadPoolExecutor = threadContainer.get(key).getThreadPoolExecutor();
		threadPoolExecutor.shutdown();
		return threadPoolExecutor.isShutdown();
	}

	/**
	 * 强制停止线程
	 * 
	 * @param key    线程分发key
	 * @param number
	 * @return boolean
	 */
	public synchronized static boolean forceShutdownThreadPool(String key) {
		ThreadPoolExecutor threadPoolExecutor = threadContainer.get(key).getThreadPoolExecutor();
		threadPoolExecutor.shutdownNow();
		return threadPoolExecutor.isShutdown();
	}

	/**
	 * 并行提数的线程数
	 * @return
	 */
	private static int getDefaultThreadNumber() {
		return DEFAULT_MAX_THREAD_NUM;
	}

	private static String getThreadKey(Class<?> clz, String tag) {
		return clz.getName() + "--" + tag;
	}

	private static ThreadPoolDispatcherEntity getThreadDispatcherEntity(String key,
			ThreadPoolExecutor threadPoolExecutor) {
		ThreadPoolDispatcherEntity threadDispatcherEntity = new ThreadPoolDispatcherEntity();
		threadDispatcherEntity.setKey(key);
		threadDispatcherEntity.setStartDate(new Date());
		threadDispatcherEntity.setThreadPoolExecutor(threadPoolExecutor);
		return threadDispatcherEntity;
	}

}
